<%
'######################################################################
'## ab.list.asp
'## -------------------------------------------------------------------
'## Feature     :   AspBox List(Array) Class
'## Version     :   v1.0
'## Author      :   Lajox(lajox@19www.com)
'## Update Date :   2012/06/08 1:01
'## Description :   A super Array class in AspBox
'##                 Support Array and Hash (like Dictionary Object)
'######################################################################

Class Cls_AB_List
	Public Size, OverError
	Private o_hash, o_map
	Private a_list
	Private i_count, i_comp

	Private Sub Class_Initialize
		Set o_hash = Server.CreateObject(AB.dictName)
		Set o_map  = Server.CreateObject(AB.dictName)
		a_list = Array()
		Size = 0
		OverError = True
		AB.Error(41) = "下标越界"
		AB.Error(42) = "下标不能为空"
		AB.Error(43) = "下标只能是数字、字母、下划线(_)、点(.)和斜杠(/)组成"
		AB.Error(44) = "参数必须是数组或者List对象"
		i_comp = 1
	End Sub

	Private Sub Class_Terminate
		Set o_map  = Nothing
		Set o_hash = Nothing
	End Sub

	Public Function [New]()
		Set [New] = New Cls_AB_List
		[New].IgnoreCase = Me.IgnoreCase
	End Function

	Public Function NewArray(ByVal a)
		Set NewArray = New Cls_AB_List
		NewArray.IgnoreCase = Me.IgnoreCase
		NewArray.Data = a
	End Function

	Public Function NewHash(ByVal a)
		Set NewHash = New Cls_AB_List
		NewHash.IgnoreCase = Me.IgnoreCase
		NewHash.Hash = a
	End Function

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.IgnoreCase[ = boolean] 设置和查询数组操作时是否忽略数组值的大小写，此属性可读可写
	'@ 返  回:  忽略大小写则返回真（True），不忽略则返回假（False）
	'@ 作  用:  此属性一般在去重复项、搜索、取索引值、排序、比较等数组操作时设置，如不设置此属性，则默认为忽略（True）。
	'==DESC=====================================================================================
	'@ 参数 boolean(可选) : Boolean (布尔值) 设置是否忽略数组值的大小写
	'==DEMO=====================================================================================
	'@ 无
	'@ *****************************************************************************************

	Public Property Let IgnoreCase(ByVal b)
		i_comp = AB.C.IIF(b, 1, 0)
	End Property

	Public Property Get IgnoreCase
		IgnoreCase = (i_comp = 1)
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.At(index)[ = value] 别名 AB.List(index)[ = value]
	'@ 返  回:  返回数组指定下标的值
	'@			[Array (数组) 或 Boolean (布尔值) 或 Datetime (时间日期) 或 Numeric (数值) 或 String (字符串)]
	'@ 作  用:  根据下标设置或获取数组某一项的值 AB.List.At(index)可以简写为AB.List(index)
	'==DESC=====================================================================================
	'@ 参数 index : Integer (整数) 或 String (字符串) 
	'@ 				数组的下标，只能由自然数、字母、下划线(_)、点(.)和斜杠(/)组成。
	'@ 				数组是普通数组时，下标就是自然数；数组是Hash数组时，下标除了可以是自然数之外，还可以是非空字符串。 
	'@ 参数 value(可选) : Array (数组) 或 Boolean (布尔值) 或 Datetime (时间日期) 或 Numeric (数值) 或 String (字符串) 
	'@ 				被设置的数组的值 
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Data = Array("零", "壹", "贰", "叁")
	'@ list.At(2) = "二" '设置下标为2的数组值为“二”
	'@ list(5) = "伍" '设置下标为5的数组值为“伍”
	'@ '此时数组已经变成：Array("零", "壹", "二", "叁", "", "伍")
	'@ AB.C.PrintCn list(3) '输出下标为3的数组值,页面将显示：叁
	'@ Dim list2 : Set list2 = AB.List.New 
	'@ list2.Hash = "zero:零 one:壹 two:贰 three:叁"
	'@ list2("ten") = "拾"
	'@ AB.C.PrintCn list2("ten") '页面将显示：拾
	'@ AB.C.PrintCn list2(4) '仍可以使用数字下标,页面将显示：拾
	'@ *****************************************************************************************

	Public Property Let At(ByVal n, ByVal v)
		If AB.C.IsNul(n) Then AB.Error.Raise 42 : Exit Property
		If AB.C.Test(n,"^\d+$") Then
			If n > [End] Then
				ReDim Preserve a_list(n)
				Size = n + 1
			End If
			a_list(n) = v
		ElseIf AB.C.Test(n,"^[\w\./]+$") Then
			If Not o_map.Exists(n) Then
				o_map(n) = Size
				o_map(Size) = n
				Push v
			Else
				a_list(o_map(n)) = v
			End If
		Else
			AB.Error.Raise 43
		End If
	End Property

	Public Default Property Get At(ByVal n)
		If AB.C.Test(n,"^\d+$") Then
			If n < Size Then
				At = a_list(n)
			Else
				At = Null
				If OverError Then
					AB.Error.Msg = "(当前下标 " & n & " 超过了最大下标 " & [End] & " )"
					AB.Error.Raise 41
				End If
			End If
		ElseIf AB.C.Test(n,"^[\w-\./]+$") Then
			If o_map.Exists(n) Then
				At = a_list(o_map(n))
			Else
				At = Null
				If OverError Then
					AB.Error.Msg = "(当前列 " & n & " 不在数组Hash列中)"
					AB.Error.Raise 41
				End If
			End If
		End If
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Data[ = content] 设置源数组为简单数组并赋值，此属性可读可写
	'@ 返  回:  Array (数组) 取出为普通数组
	'@ 作  用:  创建一个List对象后，通过此方法赋值，该对象就是普通数组。
	'==DESC=====================================================================================
	'@ 参数 content(可选) : Array (数组) 或 String (字符串) 
	'@ 		可以是数组，也可以是以空格分隔的字符串
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ 'list.Data = Array("零", "壹", "贰", "叁")
	'@ list.Data = "零 壹 贰 叁" '通过以空格分隔的字符串赋值
	'@ Dim i, arr : arr = list.Data '取出为普通数组
	'@ For i = 0 To Ubound(arr)
	'@  AB.C.PrintCn "arr("&i&") 的值是：" & arr(i)
	'@ Next
	'@ *****************************************************************************************

	Public Property Let Data(ByVal a)
		Data__ a, 0
	End Property

	Public Property Get Data
		Data = a_list
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Hash[ = content] 设置和查询数组操作时是否忽略数组值的大小写，此属性可读可写
	'@ 返  回:  Array (数组) 取出为普通数组，每个元素的值包含源Hash的列名和列值。
	'@ 作  用:  创建一个List对象后，通过此方法赋值，该对象就是Hash数组。
	'==DESC=====================================================================================
	'@ 参数 content(可选) : Array (数组) 或 String (字符串) 
	'@ 		可以是数组，也可以是以空格分隔的字符串。
	'@ 		数组的每个元素或者字符串的每个成员，都必须用冒号(:)分隔，
	'@ 		冒号左边的部分就是Hash的列名（即字符串下标）。
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ 'list.Hash = Array("zero:零", "one:壹", "two:贰", "three:叁") '通过数组赋值
	'@ list.Hash = "zero:零 one:壹 two:贰 three:叁" '通过以空格分隔的字符串赋值
	'@ Dim i, arr : arr = list.Hash '取出为普通数组
	'@ For i = 0 To Ubound(arr)
	'@  AB.C.PrintCn "arr("&i&") 的值是：" & arr(i)
	'@ Next
	'@ --运行结果为:	
	'@ arr(0) 的值是：zero:零
	'@ arr(1) 的值是：one:壹
	'@ arr(2) 的值是：two:贰
	'@ arr(3) 的值是：three:叁
	'@ *****************************************************************************************

	Public Property Let Hash(ByVal a)
		Data__ a, 1
	End Property

	Public Property Get Hash
		Dim arr, i
		arr = a_list
		For i = 0 To [End]
			If o_map.Exists(i) Then
				arr(i) = o_map(i) & ":" & arr(i)
			End If
		Next
		Hash = arr
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Maps [ = hash ] 将Hash数组映射为 Dictionary 对象，此属性可读可写
	'@ 返  回:  返回 Dictionary 对象。
	'@ 作  用:  转换为 Dictionary 对象后，可对其使用 Dictionary 对象自有的属性和方法。
	'==DESC=====================================================================================
	'@ 参数 hash(可选) : Array (数组)
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Maps = AB.Dict
	'@ AB.Trace list.Maps
	'@ *****************************************************************************************

	Public Property Let Maps(ByVal d)
		If TypeName(d) = "Dictionary" Then CloneDic__ o_map, d
	End Property

	Public Property Get Maps
		Set Maps = o_map
	End Property

	'------------------------------------------------------------------------------------------
	'# AB.List.Size 属性(只读)
	'# @syntax: AB.List.Size
	'# @alias:  AB.List.Length
	'# @return: Integer (整数) 返回当前数组的长度（元素个数）。
	'# @dowhat: 返回当前数组的长度（元素个数），此属性只读
	'#  此使用该属性可以返回当前List数组的元素个数，即数组的长度。
	'--DESC------------------------------------------------------------------------------------
	'# @param: none
	'--DEMO------------------------------------------------------------------------------------
	'# '加载List核心
	'# AB.Use "List"
	'# Dim list : Set list = AB.List.New
	'# '把数组存入List对象管理
	'# 'list.Data = Array("aa", "bb", "cc")
	'# list.Data = "aa bb cc"
	'# AB.C.PrintCn "数组为：" & list.ToString '返回结果：aa,bb,cc
	'# AB.C.PrintCn "数组的长度（元素个数）是：" & list.Size '返回结果：数组的长度（元素个数）是：3
	'------------------------------------------------------------------------------------------

	Public Property Get Length
		Length = Size
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Count 返回数组的有效长度（非空值），此属性只读
	'@ 返  回:  无参数
	'@ 作  用:  返回数组中非空值的有效元素个数
	'==DESC=====================================================================================
	'@ 参数 无
	'==DEMO=====================================================================================
	'@ AB.Use "List"
	'@ Dim list : Set list = AB.List.New
	'@ AB.List.Data = "aa bb cc" '把数组存入List对象管理
	'@ AB.List(8) = "dd" '可以向超过当前最大下标的元素赋值，相当于添加元素
	'@ AB.C.PrintCn "数组为：" & AB.List.ToString
	'@ AB.C.PrintCn "数组的长度（元素个数）是：" & AB.List.Size
	'@ AB.C.PrintCn "数组的有效长度（非空值）是：" & AB.List.Count
	'@ --运行结果为：
	'@ 数组为：aa,bb,cc,,,,,,dd
	'@ 数组的长度（元素个数）是：9
	'@ 数组的有效长度（非空值）是：4
	'@ *****************************************************************************************

	Public Property Get Count
		Dim i,j : j = 0
		For i = 0 To Size-1
			If AB.C.Has(At(i)) Then j = j + 1
		Next
		Count = j
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.End 返回数组的最大数字下标，此属性只读
	'@ 返  回:  无参数
	'@ 作  用:  返回数组的最大数字下标
	'==DESC=====================================================================================
	'@ 参数 无
	'==DEMO=====================================================================================
	'@ AB.Use "List"
	'@ Dim list : Set list = AB.List.New
	'@ list.Data = "零 壹 贰 叁"
	'@ AB.C.Print list.End '页面将显示：3
	'@ *****************************************************************************************

	Public Property Get [End]
		[End] = Size - 1
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.First 返回数组第一个元素的值，此属性只读
	'@ 返  回:  [ Boolean (布尔值) 或 Datetime (时间日期) 或 Numeric (数值) 或 String (字符串) ]
	'@ 作  用:  返回数组第一个元素的值
	'==DESC=====================================================================================
	'@ 参数 无
	'==DEMO=====================================================================================
	'@ AB.Use "List" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Hash = "zero:零 one:壹 two:贰 three:叁"
	'@ AB.C.Print list.First '页面将显示：零（注意不是：zero:零）
	'@ *****************************************************************************************

	Public Property Get First
		First = At(0)
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Last 返回数组最后一个元素的值，此属性只读
	'@ 返  回:  [ Boolean (布尔值) 或 Datetime (时间日期) 或 Numeric (数值) 或 String (字符串) ]
	'@ 作  用:  返回数组最后一个元素的值
	'==DESC=====================================================================================
	'@ 参数 无
	'==DEMO=====================================================================================
	'@ AB.Use "List" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Hash = "zero:零 one:壹 two:贰 three:叁"
	'@ AB.C.Print list.Last '页面将显示：叁（注意不是：three:叁）
	'@ *****************************************************************************************

	Public Property Get Last
		Last = At([End])
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Max 返回数组最大元素的值，此属性只读
	'@ 返  回:  返回数组最大元素的值 [ Boolean (布尔值) 或 Datetime (时间日期) 或 Numeric (数值) 或 String (字符串) ]
	'@ 作  用:  如果数组元素的值是字符串，将通过StrComp函数的“文本比较”方法取得最小值。
	'@			数组中所有元素的类型必须都符合返回值类型才能准确获取最大值，否则会报错。
	'==DESC=====================================================================================
	'@ 参数 无
	'==DEMO=====================================================================================
	'@ AB.Use "List" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Data = Array(0, -1, 3.6)
	'@ AB.C.PrintCn list.Max '页面将显示：3.6
	'@ Dim list2 : Set list2 = AB.List.New
	'@ list2.Data = Array("大", "小")
	'@ AB.C.PrintCn list2.Max '页面将显示：小
	'@ *****************************************************************************************

	Public Property Get Max
		Dim i, v
		v = At(0)
		If Size > 1 Then
			For i = 1 To [End]
				If Compare__("gt", At(i), v) Then v = At(i)
			Next
		End If
		Max = v
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Min 返回数组最小元素的值，此属性只读
	'@ 返  回:  返回数组最小元素的值 [ Boolean (布尔值) 或 Datetime (时间日期) 或 Numeric (数值) 或 String (字符串) ]
	'@ 作  用:  如果数组元素的值是字符串，将通过StrComp函数的“文本比较”方法取得最小值。
	'@			数组中所有元素的类型必须都符合返回值类型才能准确获取最小值，否则会报错。
	'==DESC=====================================================================================
	'@ 参数 无
	'==DEMO=====================================================================================
	'@ AB.Use "List" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Data = Array(0, -1, 3.6)
	'@ AB.C.PrintCn list.Min '页面将显示：-1
	'@ Dim list2 : Set list2 = AB.List.New
	'@ list2.Data = Array("大", "小")
	'@ AB.C.PrintCn list2.Min '页面将显示：大
	'@ *****************************************************************************************

	Public Property Get Min
		Dim i, v
		v = At(0)
		If Size > 1 Then
			For i = 1 To [End]
				If Compare__("lt", At(i), v) Then v = At(i)
			Next
		End If
		Min = v
	End Property

	'------------------------------------------------------------------------------------------
	'# AB.List.Serialize 属性(只读)
	'# @syntax: AB.List.Serialize
	'# @return: String (字符串) 返回数组被序列化后的字符串。
	'# @dowhat: 序列化Hash数组，此属性只读
	'#  如果在使用GET或者POST方式获取远程数据时，可以通过此属性同时提交数据。
	'#  GET会以URL参数的方式附加这些数据，POST则会类似表单一样提交这些数据。
	'--DESC------------------------------------------------------------------------------------
	'# @param: none
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "List" '加载List核心
	'# Dim list : Set list = AB.List.New '创建一个List对象
	'# list.Hash = "id:1 name:wo_is神仙"
	'# AB.C.Print list.Serialize
	'# '页面将显示：id=1&name=wo%5Fis%E7%A5%9E%E4%BB%99
	'------------------------------------------------------------------------------------------

	Public Property Get Serialize
		Dim tmp, i : tmp = ""
		For i = 0 To [End]
			If o_map.Exists(i) Then
				tmp = tmp & "&" & o_map(i) & "=" & Server.URLEncode(At(i))
			End If
		Next
		If Len(tmp)>1 Then tmp = Mid(tmp,2)
		Serialize = tmp
	End Property

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.HasIndex index 检测是否包含某个下标
	'@ 返  回:  存在指定下标的元素返回真（True），否则返回假（False）
	'@ 作  用:  检测是否包含某个下标
	'==DESC=====================================================================================
	'@ 参数 index : 可以使用数字下标检测，也可以使用字符串下标检测。
	'==DEMO=====================================================================================
	'@ AB.Use "list"
	'@ Dim list : Set list = AB.List.New
	'@ list.Hash = "zero:零 one:壹 two:贰 three:叁"
	'@ AB.C.Print "数组" & AB.C.IIF(list.HasIndex("one"), "存在", "不存在") & "下标为""one""的元素"
	'@ *****************************************************************************************

	Public Function HasIndex(ByVal i)
		HasIndex = Index(i) >= 0
	End Function

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Index index 根据Hash的列名获取其数字下标
	'@ 返  回:  如果Hash存在指定列名的元素则返回其数字下标，不存在则返回-1
	'@ 作  用:  根据Hash的列名获取其数字下标，此方法一般用于Hash数组。
	'==DESC=====================================================================================
	'@ 参数 index : 非空字符串
	'==DEMO=====================================================================================
	'@ AB.Use "list"
	'@ Dim list : Set list = AB.List.New
	'@ list.Hash = "zero:零 one:壹 two:贰 three:叁"
	'@ AB.C.Print "Hash数组中列名为""one""的元素的数字下标是：" & list.Index("one")
	'@ *****************************************************************************************

	Public Function Index(ByVal i)
		If isNumeric(i) Then
			Index = AB.C.IIF(i >= 0 And i <= [End], i, -1)
		Else
			If o_map.Exists(i) Then
				Index = o_map(i)
			Else
				Index = -1
			End If
		End If
	End Function

	Public Function IndexHash(ByVal i)
		If isNumeric(i) Then
			IndexHash = AB.C.IfThen(o_map.Exists(i), o_map(i))
		Else
			IndexHash = AB.C.IfThen(o_map.Exists(i), i)
		End If
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Xml.UnShift 方法
	'# @syntax: AB.List.UnShift content
	'# @return: 无返回值
	'# @dowhat: 添加一个或多个元素到List数组的开头
	'# 当content为字符串时，就是添加一个元素；当content为数组时，就是添加多个元素。
	'--DESC------------------------------------------------------------------------------------
	'# @param content : Array (数组) 或 String (字符串) 
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "list" '加载List核心
	'# Dim list : Set list = AB.List.New '创建一个List对象
	'# list.Hash = "zero:零 one:壹 two:贰 three:叁"
	'# '使用数组同时添加两个元素
	'# list.UnShift Array("a:aaa", "b:bbb")
	'# '取出为普通数组
	'# Dim i,arr : arr = list.Hash
	'# '循环输出
	'# For i = 0 To Ubound(arr)
	'# 	AB.C.PrintCn("arr("& i &") => " & arr(i))
	'# Next
	'# ------本示例运行结果为：
	'# arr(0) => a:aaa
	'# arr(1) => b:bbb
	'# arr(2) => zero:零
	'# arr(3) => one:壹
	'# arr(4) => two:贰
	'# arr(5) => three:叁
	'------------------------------------------------------------------------------------------

	Public Sub UnShift(ByVal v)
		Insert 0, v
	End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Xml.UnShift_ 方法
	'# @syntax: AB.List.UnShift_ content
	'# @return: Object (ASP对象) 返回一个新的AspBox的List对象，原List对象不受影响。
	'# @dowhat: 添加一个或多个元素到数组的开头，返回新的List对象
	'#  当content为字符串时，就是添加一个元素；当content为数组时，就是添加多个元素。
	'#  原数组的数据加上新添加的数据，组成新的数组对象，不改变原数组的数据。
	'--DESC------------------------------------------------------------------------------------
	'# @param content : Array (数组) 或 String (字符串) 
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "list" '加载List核心
	'# Dim list : Set list = AB.List.New '创建一个List对象
	'# list.Hash = "zero:零 one:壹 two:贰 three:叁"
	'# '取出为普通数组
	'# Dim arr, arr2, i
	'# arr = list.Hash '原数组
	'# arr2 = list.UnShift_(Array("a:aaa", "b:bbb")).Hash '新数组
	'# '循环输出
	'# For i = 0 To Ubound(arr)
	'# 	AB.C.PrintCn("arr("& i &") => " & arr(i))
	'# Next
	'# AB.C.PrintCn "============"
	'# For i = 0 To Ubound(arr2)
	'# 	AB.C.PrintCn("arr2("& i &") => " & arr2(i))
	'# Next
	'# ------本示例运行结果为：
	'# arr(0) => zero:零 
	'# arr(1) => one:壹 
	'# arr(2) => two:贰 
	'# arr(3) => three:叁 
	'# ============ 
	'# arr2(0) => a:aaa 
	'# arr2(1) => b:bbb 
	'# arr2(2) => zero:零 
	'# arr2(3) => one:壹 
	'# arr2(4) => two:贰 
	'# arr2(5) => three:叁
	'------------------------------------------------------------------------------------------

	Public Function UnShift_(ByVal v)
		Set UnShift_ = Me.Clone
		UnShift_.UnShift v
	End Function

	'------------------------------------------------------------------------------------------
	'# AB.Xml.Shift 方法
	'# @syntax: AB.List.Shift
	'# @return: 无返回值
	'# @dowhat: 删除数组的第一个元素
	'# 使用该方法可以删除数组的第一个元素。
	'--DESC------------------------------------------------------------------------------------
	'# @param: 无参数
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "list" '加载List核心
	'# Dim list : Set list = AB.List.New '创建一个List对象
	'# list.Data = "zero:零 one:壹 two:贰 three:叁"
	'# '删除第一个元素
	'# list.Shift
	'# '输出
	'# AB.C.Print list.ToString '输出结果：one:壹,two:贰,three:叁
	'------------------------------------------------------------------------------------------

	Public Sub Shift
		[Delete] 0
	End Sub

	'------------------------------------------------------------------------------------------
	'# AB.Xml.Shift_ 方法
	'# @syntax: AB.List.Shift_
	'# @return: Object (ASP对象) 返回一个新的AspBox的List对象，原List对象不受影响。
	'# @dowhat: 删除数组的第一个元素，返回新的List对象
	'# 使用该方法可以删除数组的第一个元素，剩下的元素组成新的数组对象，不改变原数组的数据。
	'--DESC------------------------------------------------------------------------------------
	'# @param: 无参数
	'--DEMO------------------------------------------------------------------------------------
	'# AB.Use "list" '加载List核心
	'# Dim list : Set list = AB.List.New '创建一个List对象
	'# list.Data = "zero:零 one:壹 two:贰 three:叁"
	'# '输出
	'# AB.C.PrintCn "新数组：" & list.Shift_.ToString '输出结果：新数组：one:壹,two:贰,three:叁
	'# AB.C.PrintCn "原数组：" & list.ToString '输出结果：原数组：zero:零,one:壹,two:贰,three:叁
	'------------------------------------------------------------------------------------------

	Public Function Shift_
		Set Shift_ = Me.Clone
		Shift_.Shift
	End Function

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Push Str 添加一个元素到List数组的末尾
	'@ 返  回:  无返回值
	'@ 作  用:  使用该方法可以向普通List数组的末尾添加一个新的元素。
	'==DESC=====================================================================================
	'@ 参数 Str : Boolean (布尔值) 或 Datetime (时间日期) 或 Numeric (数值) 或 String (字符串)
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Data = "零 壹 贰 叁" '设置为普通数组并赋值
	'@ list.Push "肆"
	'@ AB.C.Put list.ToString '页面将显示：零,壹,贰,叁,肆
	'@ *****************************************************************************************

	Public Sub Push(ByVal v)
		ReDim Preserve a_list(Size)
		a_list(Size) = v
		Size = Size + 1
	End Sub

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Push_ Str 添加一个元素到List数组的末尾，返回新的List对象
	'@ 返  回:  返回一个新的AspBox的List对象，原List对象不受影响。
	'@ 作  用:  使用该方法可以向普通List数组的末尾添加一个新的元素，
	'@ 			新老元素一起组成一个新的List对象，原List的数据不会改变。
	'==DESC=====================================================================================
	'@ 参数 Str : Boolean (布尔值) 或 Datetime (时间日期) 或 Numeric (数值) 或 String (字符串)
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Data = "零 壹 贰 叁" '设置为普通数组并赋值
	'@ Dim NewList : Set NewList = list.Push_("肆")
	'@ AB.C.Put NewList.ToString '页面将显示：零,壹,贰,叁,肆
	'@ *****************************************************************************************

	Public Function Push_(ByVal v)
		Set Push_ = Me.Clone
		Push_.Push v
	End Function

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Pop Str 添加一个元素到数组的末尾
	'@ 返  回:  无返回值
	'@ 作  用:  使用该方法可以向普通数组的末尾添加一个新的元素。
	'==DESC=====================================================================================
	'@ 参数 Str : Boolean (布尔值) 或 Datetime (时间日期) 或 Numeric (数值) 或 String (字符串)
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Set list = AB.List.New '创建一个List对象
	'@ list.Data = "zero:零 one:壹 two:贰 three:叁" '设置为普通数组并赋值
	'@ list.Pop '删除第一个元素
	'@ AB.C.Print list.ToString '页面将显示：zero:零,one:壹,two:贰
	'@ *****************************************************************************************

	Public Sub Pop
		RemoveMap__ [End]
		ReDim Preserve a_list([End]-1)
		Size = Size - 1
	End Sub

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Pop_ Str 添加一个元素到数组的末尾，返回新的List对象
	'@ 返  回:  返回一个新的AspBox的List对象，原List对象不受影响。
	'@ 作  用:  使用该方法可以向普通数组的末尾添加一个新的元素，
	'@ 			新老元素一起组成一个新的List对象，原List的数据不会改变。
	'==DESC=====================================================================================
	'@ 参数 Str : Boolean (布尔值) 或 Datetime (时间日期) 或 Numeric (数值) 或 String (字符串)
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Data = "zero:零 one:壹 two:贰 three:叁" '设置为普通数组并赋值
	'@ AB.C.PrintCn "新数组：" & list.Pop_.ToString '显示结果：新数组：zero:零,one:壹,two:贰
	'@ AB.C.PrintCn "原数组：" & list.ToString '将显示：原数组：zero:零,one:壹,two:贰,three:叁
	'@ *****************************************************************************************

	Public Function Pop_
		Set Pop_ = Me.Clone
		Pop_.Pop
	End Function

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Insert index, content 向指定数字下标处插入一个或多个元素
	'@ 返  回:  无返回值
	'@ 作  用:  向指定数字下标处插入一个或多个元素, index允许大于数组的最大下标；
	'@			当content为字符串时，就是插入一个元素；当content为数组时，就是插入多个元素。
	'==DESC=====================================================================================
	'@ 参数 index : Integer (整数) 准备插入元素的位置的下标，可以大于数组当前的最大下标。
	'@ 参数 content : Array (数组) 或 String (字符串) 准备插入元素的内容。
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Data = "零 壹 贰 叁" '设置为普通数组并赋值
	'@ list.Insert 2, "AspBox"
	'@ AB.C.PrintCn "第一次插入元素后：" & list.ToString & "，数组长度为：" & list.Size
	'@ list.Insert 7, Array("柒", "捌", "玖")
	'@ AB.C.PrintCn "第二次插入元素后：" & list.ToString & "，数组长度为：" & list.Size
	'@ --运行结果为：
	'@ 第一次插入元素后：零,壹,AspBox,贰,叁，数组长度为：5
	'@ 第二次插入元素后：零,壹,AspBox,贰,叁,,,柒,捌,玖，数组长度为：10
	'@ *****************************************************************************************

	Public Sub Insert(ByVal n, ByVal v)
		Dim i,j
		If n > [End] Then
			If isArray(v) Then
				For i = 0 To UBound(v)
					At(n+i) = v(i)
				Next
			Else
				At(n) = v
			End If
		Else
			For i = Size To (n+1) Step -1
				If isArray(v) Then
					UpFrom__ i+UBound(v), i-1
				Else
					UpFrom__ i, i-1
				End If
			Next
			If isArray(v) Then
				For i = 0 To UBound(v)
					At(n+i) = v(i)
				Next
			Else
				At(n) = v
			End If
		End If
	End Sub

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Insert_ index, content 向指定数字下标处插入一个或多个元素，返回新的List对象
	'@ 返  回:  无返回值
	'@ 作  用:  返回一个新的AspBox的List对象，原List对象不受影响。index允许大于数组的最大下标；
	'@			当content为字符串时，就是插入一个元素；当content为数组时，就是插入多个元素。
	'@			使用该方法，返回的是插入新元素后的新数组对象，不改变原数组的数据。
	'==DESC=====================================================================================
	'@ 参数 index : Integer (整数) 准备插入元素的位置的下标，可以大于数组当前的最大下标。
	'@ 参数 content : Array (数组) 或 String (字符串) 准备插入元素的内容。
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Data = "零 壹 贰 叁" '设置为普通数组并赋值
	'@ AB.C.PrintCn "新数组：" & list.Insert_(7, Array("柒", "捌", "玖")).ToString
	'@ AB.C.PrintCn "老数组：" & list.ToString
	'@ --运行结果为：
	'@ 新数组：零,壹,贰,叁,,,,柒,捌,玖
	'@ 老数组：零,壹,贰,叁
	'@ *****************************************************************************************

	Public Function Insert_(ByVal n, ByVal v)
		Set Insert_ = Me.Clone
		Insert_.Insert n, v
	End Function

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Has element 检测数组中是否包含某个元素
	'@ 返  回:  包含则返回真（True），不包含返回假（False）
	'@ 作  用:  使用该方法可以检测数组中是否包含某个元素，如果是Hash数组的话，检测的目标仅是列值，不能检测列名。
	'==DESC=====================================================================================
	'@ 参数 element : Anything (任意值) 被检测的对象
	'==DEMO=====================================================================================
	'@ AB.Use "list"
	'@ Dim list : Set list = AB.List.New
	'@ list.Hash = "zero:零 one:壹 two:贰 three:叁"
	'@ AB.C.PrintCn "是否包含字符串 ""壹"" ：" & list.Has("壹")
	'@ AB.C.PrintCn "是否包含字符串 ""two"" ：" & list.Has("two")
	'@ --运行结果为：
	'@ 是否包含字符串 "壹" ：True
	'@ 是否包含字符串 "two" ：False
	'@ *****************************************************************************************

	Public Function Has(ByVal v)
		Has = (indexOf__(a_list, v) > -1)
	End Function

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.IndexOf element 检测元素在数组中的数字下标
	'@ 返  回:  Integer (整数) 数组中存在element就返回所属下标，不存在则返回-1。
	'@ 作  用:  使用该方法可以检测元素element在数组中的数字下标，如果有多个相同的元素，返回的是第一次出现的下标。
	'==DESC=====================================================================================
	'@ 参数 element : Anything (任意值) 被检测的对象
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Hash = "zero:零 one:壹 two:贰 three:叁" '设置为Hash数组并赋值
	'@ AB.C.PrintCn "字符串""贰""在数组中第一次出现的下标是：" & list.IndexOf("贰")
	'@ AB.C.PrintCn "数组 " & AB.C.IIF(list.IndexOf("伍") > -1, "存在", "不存在") & " 值为""伍""的元素"
	'@ --运行结果为：
	'@ 字符串"贰"在数组中第一次出现的下标是：2
	'@ 数组 不存在 值为"伍"的元素
	'@ *****************************************************************************************

	Public Function IndexOf(ByVal v)
		IndexOf = indexOf__(a_list, v)
	End Function

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.IndexOfHash element 检测元素在Hash数组中的字符串下标
	'@ 返  回:  无返回值
	'@ 作  用:  Hash数组中存在element就返回所属字符串下标，不存在则返回空。
	'@			使用该方法可以检测元素element在Hash数组中的字符串下标，
	'@			如果有多个相同的元素，返回的是第一次出现的下标。
	'==DESC=====================================================================================
	'@ 参数 element : Anything (任意值) 被检测的对象
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Hash = "zero:零 one:壹 two:贰 three:叁" '设置为Hash数组并赋值
	'@ AB.C.PrintCn "字符串""贰""在数组中第一次出现的下标是：" & list.IndexOfHash("贰")
	'@ AB.C.PrintCn "数组 " & AB.C.IIF(AB.C.Has(list.IndexOfHash("伍")), "存在", "不存在") & " 值为""伍""的元素"
	'@ --运行结果为：
	'@ 字符串"贰"在数组中第一次出现的下标是：two
	'@ 数组 不存在 值为"伍"的元素
	'@ *****************************************************************************************

	Public Function IndexOfHash(ByVal v)
		Dim i : i = indexOf__(a_list, v)
		If i = -1 Then IndexOfHash = Empty : Exit Function
		If o_map.Exists(i) Then
			IndexOfHash = o_map(i)
		Else
			IndexOfHash = Empty
		End If
	End Function

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Delete index 删除指定下标的数组元素
	'@ 返  回:  无返回值
	'@ 作  用:  使用此方法可以删除指定下标的数组元素，可以只删除一个，也可以同时删除多个。
	'@			index可以是自然数，也可以是字符串，还可以是数字区间。
	'==DESC=====================================================================================
	'@ 参数 index : Integer (整数) 被删除元素的下标，可以是数字，抑或是Hash的列名。
	'@ 				同时删除多个元素时，还可以指定下标的区间，用 - 表示区间，\s 表示开头，\e 表示结尾。
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Hash = "zero:零 one:壹 two:贰 three:叁 four:肆 five:伍 six:陆 seven:柒 eight:捌 nine:玖" '设置为Hash数组并赋值 
	'@ list.Delete 1 '通过数字下标删除一个元素
	'@ AB.C.PrintCn "删除数字下标为1的元素后：" & list.ToString
	'@ list.Delete "two,six" '通过字符串下标删除两个元素
	'@ AB.C.PrintCn "删除字符串下标为""two""和""six""的元素后：" & list.ToString
	'@ AB.C.PrintCn "此时数组的长度为：" & list.Size & "，最大数字下标是：" & list.End
	'@ '通过区间删除下标为0到2，以及下标为5的四个元素（用 - 表示区间, \s 表示开头, \e 表示结尾）
	'@ list.Delete "\s-2,5"
	'@ AB.C.PrintCn "删除下标为""开头-2""和""5""的元素后：" & list.ToString
	'@ --运行结果为：
	'@ 删除数字下标为1的元素后：零,贰,叁,肆,伍,陆,柒,捌,玖
	'@ 删除字符串下标为"two"和"six"的元素后：零,叁,肆,伍,柒,捌,玖
	'@ 此时数组的长度为：7，最大数字下标是：6
	'@ 删除下标为"开头-2"和"5"的元素后：伍,柒,玖
	'@ *****************************************************************************************

	Public Sub [Delete](ByVal n)
		Dim tmp,a,x,y,i
		If Instr(n, ",")>0 Or Instr(n,"-")>0 Then
			n = Replace(n,"\s","0")
			n = Replace(n,"\e",[End])
			a = Split(n, ",")
			For i = 0 To Ubound(a)
				If i>0 Then tmp = tmp & ","
				If Instr(a(i),"-")>0 Then
					x = Trim(AB.C.CLeft(a(i),"-"))
					y = Trim(AB.C.CRight(a(i),"-"))
					If Not Isnumeric(x) And o_map.Exists(x) Then x = o_map(x)
					If Not Isnumeric(y) And o_map.Exists(y) Then y = o_map(y)
					tmp = tmp & x & "-" & y
				Else
					x = Trim(a(i))
					If Not Isnumeric(x) And o_map.Exists(x) Then x = o_map(x)
					tmp = tmp & x
				End If
			Next
			a = Split(tmp,",")
			a = SortArray(a,0,UBound(a))
			tmp = "0-"
			For i = 0 To Ubound(a)
				If Instr(a(i),"-")>0 Then
					x = AB.C.CLeft(a(i),"-")
					y = AB.C.CRight(a(i),"-")
					tmp = tmp & x-1 & ","
					tmp = tmp & y+1 & "-"
				Else
					tmp = tmp & a(i)-1 & "," & a(i)+1 & "-"
				End If
			Next
			tmp = tmp & [End]
			Slice tmp
		Else
			If Not isNumeric(n) And o_map.Exists(n) Then
				n = o_map(n)
				RemoveMap__ n
			End If
			For i = n+1 To [End]
				UpFrom__ i-1, i
			Next
			Pop
		End If
	End Sub

	'@ *****************************************************************************************
	'@ 过程名:  AB.List.Delete_ index 删除指定下标的数组元素，返回新的List对象
	'@ 返  回:  返回一个新的AspBox的List对象，原List对象不受影响
	'@ 作  用:  使用此方法可以删除指定下标的数组元素，可以只删除一个，也可以同时删除多个。
	'@			index可以是自然数，也可以是字符串，还可以是数字区间。
	'@			使用该方法，返回的是删除元素后的新数组对象，不改变原数组的数据。
	'==DESC=====================================================================================
	'@ 参数 index : Integer (整数) 被删除元素的下标，可以是数字，抑或是Hash的列名。
	'@ 				同时删除多个元素时，还可以指定下标的区间，用 - 表示区间，\s 表示开头，\e 表示结尾。
	'==DEMO=====================================================================================
	'@ AB.Use "list" '加载List核心
	'@ Dim list : Set list = AB.List.New '创建一个List对象
	'@ list.Hash = "zero:零 one:壹 two:贰 three:叁 four:肆 five:伍 six:陆 seven:柒 eight:捌 nine:玖" '设置为Hash数组并赋值 
	'@ AB.C.PrintCn "删除数字下标为1的元素后：" & list.Delete_(1).ToString '通过数字下标删除一个元素
	'@ AB.C.PrintCn "删除字符串下标为""two""和""six""的元素后：" & list.Delete_("two,six").ToString '通过字符串下标删除两个元素
	'@ AB.C.PrintCn "此时原数组的长度仍为：" & list.Size & "，最大数字下标是：" & list.End
	'@ '通过区间删除下标为0到2，以及下标为5的四个元素（用 - 表示区间, \s 表示开头, \e 表示结尾）
	'@ AB.C.PrintCn "删除下标为""开头-2""和""5""的元素后：" & list.Delete_("\s-2,5").ToString
	'@ --运行结果为：
	'@ 删除数字下标为1的元素后：零,贰,叁,肆,伍,陆,柒,捌,玖
	'@ 删除字符串下标为"two"和"six"的元素后：零,壹,叁,肆,伍,柒,捌,玖
	'@ 此时原数组的长度仍为：10，最大数字下标是：9
	'@ 删除下标为"开头-2"和"5"的元素后：叁,肆,陆,柒,捌,玖
	'@ *****************************************************************************************

	Public Function Delete_(ByVal n)
		Set Delete_ = Me.Clone
		Delete_.Delete n
	End Function

	Public Sub Uniq()
		Dim arr(),i,j : j = 0
		ReDim arr(-1)
		If o_hash.Count>0 Then o_hash.RemoveAll
		For i = 0 To [End]
			If indexOf__(arr, At(i)) = -1 Then
				ReDim Preserve arr(j)
				arr(j) = At(i)
				If o_map.Exists(i) Then
					o_hash.Add j, o_map(i)
					o_hash.Add o_map(i), j
				End If
				j = j + 1
			End If
		Next
		Data = arr
		CloneDic__ o_map, o_hash
		o_hash.RemoveAll
	End Sub

	Public Function Uniq_()
		Set Uniq_ = Me.Clone
		Uniq_.Uniq
	End Function

	Public Sub Rand
		Dim i, j, tmp, Ei, Ej, Ti, Tj
		For i = 0 To [End]
			j = AB.C.Rand(0,[End])
			Ei = o_map.Exists(i)
			Ej = o_map.Exists(j)
			If Ei Then Ti = o_map(i)
			If Ej Then Tj = o_map(j)
			tmp = At(j)
			At(j) = At(i)
			At(i) = tmp
			If Ei Then
				o_map(j) = Ti
				o_map(Ti) = j
			End If
			If Ej Then
				o_map(i) = Tj
				o_map(Tj) = i
			End If
			If Not (Ei And Ej) Then
				If Ei Then o_map.Remove i
				If Ej then o_map.Remove j
			End If
		Next
	End Sub

	Public Function Rand_()
		Set Rand_ = Me.Clone
		Rand_.Rand
	End Function

	Public Sub Reverse
		Dim arr(),i,j : j = 0
		ReDim arr([End])
		If o_hash.Count>0 Then o_hash.RemoveAll
		For i = [End] To 0 Step -1
			arr(j) = At(i)
			If o_map.Exists(i) Then
				o_hash.Add j, o_map(i)
				o_hash.Add o_map(i), j
			End If
			j = j + 1
		Next
		Data = arr
		CloneDic__ o_map, o_hash
		o_hash.RemoveAll
	End Sub

	Public Function Reverse_()
		Set Reverse_ = Me.Clone
		Reverse_.Reverse
	End Function

	Public Sub Search(ByVal s)
		Search__ s, True
	End Sub

	Public Function Search_(ByVal s)
		Set Search_ = Me.Clone
		Search_.Search s
	End Function

	Public Sub SearchNot(ByVal s)
		Search__ s, False
	End Sub

	Public Function SearchNot_(ByVal s)
		Set SearchNot_ = Me.Clone
		SearchNot_.SearchNot s
	End Function

	Public Sub Compact
		Dim arr(), i, j : j = 0
		If o_hash.Count>0 Then o_hash.RemoveAll
		For i = 0 To [End]
			If AB.C.Has(At(i)) Then
				ReDim Preserve arr(j)
				arr(j) = At(i)
				If o_map.Exists(i) Then
					o_hash.Add j, o_map(i)
					o_hash.Add o_map(i), j
				End If
				j = j + 1
			End If
		Next
		Data = arr
		CloneDic__ o_map, o_hash
		o_hash.RemoveAll
	End Sub

	Public Function Compact_()
		Set Compact_ = Me.Clone
		Compact_.Compact
	End Function

	Public Sub Clear
		a_list = Array()
		If o_map.Count>0 Then o_map.RemoveAll
		Size = 0
	End Sub

	Public Sub Sort
		Dim arr
		arr = a_list
		arr = SortArray(arr, 0, [End])
		If o_map.Count = 0 Then
			Data = arr
		Else
			AddHash__ arr
		End If
	End Sub

	Public Function Sort_()
		Set Sort_ = Me.Clone
		Sort_.Sort
	End Function

	Public Sub Slice(ByVal s)
		Dim a,i,j,k,x,y,arr
		If o_hash.Count>0 Then o_hash.RemoveAll
		s = Replace(s,"\s",0)
		s = Replace(s,"\e",[End])
		a = Split(s, ",")
		arr = Array() : k = 0
		For i = 0 To Ubound(a)
			If Instr(a(i),"-")>0 Then
				x = Trim(AB.C.CLeft(a(i),"-"))
				y = Trim(AB.C.CRight(a(i),"-"))
				If Not Isnumeric(x) And o_map.Exists(x) Then x = o_map(x)
				If Not Isnumeric(y) And o_map.Exists(y) Then y = o_map(y)
				x = Int(x) : y = Int(y)
				For j = x To y
					ReDim Preserve arr(k)
					arr(k) = At(j)
					If o_map.Exists(j) Then
						If Not o_hash.Exists(o_map(j)) Then
							o_hash.Add k, o_map(j)
							o_hash.Add o_map(j), k
						End If
					End If
					k = k + 1
				Next
			Else
				ReDim Preserve arr(k)
				x = Trim(a(i))
				If Not Isnumeric(x) And o_map.Exists(x) Then x = o_map(x)
				x = Int(x)
				If o_map.Exists(x) Then
					If Not o_hash.Exists(o_map(x)) Then
						o_hash.Add k, o_map(x)
						o_hash.Add o_map(x), k
					End If
				End If
				arr(k) = At(x)
				k = k + 1
			End If
		Next
		Data = arr
		CloneDic__ o_map, o_hash
		o_hash.RemoveAll
	End Sub

	Public Function Slice_(ByVal s)
		Set Slice_ = Me.Clone
		Slice_.Slice s
	End Function

	Public Function [Get](ByVal s)
		Set [Get] = Slice_(s)
	End Function

	Public Function J(ByVal s)
		J = Join(a_list, s)
	End Function

	Public Function ToString()
		ToString = J(",")
	End Function

	Public Function ToArray
		ToArray = a_list
	End Function

	Public Function Clone
		Set Clone = Me.New
		Clone.Data = a_list
		If o_map.Count>0 Then Clone.Maps = o_map
	End Function

	Public Sub Map(ByVal f)
		Map__ f, 0
	End Sub

	Public Function Map_(ByVal f)
		Set Map_ = Me.Clone
		Map_.Map f
	End Function

	Public Sub [Each](ByVal f)
		Map__ f, 1
	End Sub

	Public Function Find(ByVal f)
		Dim i, k, tmp
		k = "i"
		If AB.C.Test(f,"[a-zA-Z]+:(.+)") Then
			k = AB.C.CLeft(f,":")
			f = AB.C.CRight(f,":")
		End If
		k = "%" & k
		For i = 0 To [End]
			tmp = Replace(Trim(f), k, Value__(At(i)))
			If Eval(tmp) Then
				Find = At(i) : Exit Function
			End If
		Next
		Find = Empty
	End Function

	Public Sub [Select](ByVal f)
		Select__ f, 0
	End Sub

	Public Function Select_(ByVal f)
		Set Select_ = Me.Clone
		Select_.Select f
	End Function

	Public Sub Reject(ByVal f)
		Select__ f, 1
	End Sub

	Public Function Reject_(ByVal f)
		Set Reject_ = Me.Clone
		Reject_.Reject f
	End Function

	Public Sub Grep(ByVal g)
		Dim i,j,arr
		arr = Array() : j = 0
		If o_hash.Count>0 Then o_hash.RemoveAll
		For i = 0 To [End]
			If AB.C.Test(At(i),g) Then
				ReDim Preserve arr(j)
				arr(j) = At(i)
				If o_map.Exists(i) Then
					o_hash.Add j, o_map(i)
					o_hash.Add o_map(i), j
				End If
				j = j + 1
			End If
		Next
		Data = arr
		CloneDic__ o_map, o_hash
		o_hash.RemoveAll
	End Sub

	Public Function Grep_(ByVal g)
		Set Grep_ = Me.Clone
		Grep_.Grep g
	End Function

	Public Sub SortBy(ByVal f)
		Map f : Sort
	End Sub

	Public Function SortBy_(ByVal f)
		Set SortBy_ = Me.Clone
		SortBy_.SortBy f
	End Function

	Public Sub Times(ByVal t)
		Dim i, arr
		arr = a_list
		For i = 1 To t
			Insert Size, arr
		Next
	End Sub

	Public Function Times_(ByVal t)
		Set Times_ = Me.Clone
		Times_.Times t
	End Function

	Public Sub Splice(ByVal o)
		If Not isArray(o) And Not isList(o) Then AB.Error.Raise 44 : Exit Sub
		Dim omap,dic,i
		If isArray(o) Then
			Insert Size, o
		ElseIf IsList(o) Then
				Set omap = o.Maps
				If omap.Count > 0 Then
					For i = 0 To o.End
						If omap.Exists(i) And (Not o_map.Exists(omap(i))) Then
							o_map.Add Size + i, omap(i)
							o_map.Add omap(i), Size + i
						End If
					Next
				End If
				Insert Size, o.Data
		End If
	End Sub

	Public Function Splice_(ByVal o)
		Set Splice_ = Me.Clone
		Splice_.Splice o
	End Function

	Public Sub Merge(ByVal o)
		Splice o
		Uniq
	End Sub

	Public Function Merge_(ByVal o)
		Set Merge_ = Me.Clone
		Merge_.Merge o
	End Function

	Public Sub Inter(ByVal o)
		If Not isArray(o) And Not isList(o) Then AB.Error.Raise 44 : Exit Sub
		Dim i,j,k,omap,arr
		arr = Array() : j = 0
		If o_hash.Count>0 Then o_hash.RemoveAll
		If isArray(o) Then
			For i = 0 To Ubound(o)
				If Has(o(i)) Then
					ReDim Preserve arr(j)
					arr(j) = o(i)
					k = IndexOf(o(i))
					If o_map.Exists(k) Then
						o_hash.Add j, o_map(k)
						o_hash.Add o_map(k), j
					End If
					j = j + 1
				End If
			Next
		ElseIf IsList(o) Then
			Set omap = o.Maps
			For i = 0 To o.End
				If Has(o(i)) Then
					ReDim Preserve arr(j)
					arr(j) = o(i)
					k = IndexOf(o(i))
					If o_map.Exists(k) Then
						o_hash.Add j, o_map(k)
						o_hash.Add o_map(k), j
					ElseIf omap.Exists(i) Then
						o_hash.Add j, omap(i)
						o_hash.Add omap(i), j
					End If
					j = j + 1
				End If
			Next
		End If
		Data = arr
		CloneDic__ o_map, o_hash
		o_hash.RemoveAll
	End Sub

	Public Function Inter_(ByVal o)
		Set Inter_ = Me.Clone
		Inter_.Inter o
	End Function

	Public Sub Diff(ByVal o)
		If Not isArray(o) And Not isList(o) Then AB.Error.Raise 44 : Exit Sub
		Dim i,j,arr,a
		arr = Array() : j = 0
		If o_hash.Count>0 Then o_hash.RemoveAll
		If isArray(o) Then
			a = o
			Set o = Me.New
			o.Data = a
		End If
		For i = 0 To [End]
			If Not o.Has(At(i)) Then
				ReDim Preserve arr(j)
				arr(j) = At(i)
				If o_map.Exists(i) Then
					o_hash.Add j, o_map(i)
					o_hash.Add o_map(i), j
				End If
				j = j + 1
			End If
		Next
		Data = arr
		CloneDic__ o_map, o_hash
		o_hash.RemoveAll
	End Sub

	Public Function Diff_(ByVal o)
		Set Diff_ = Me.Clone
		Diff_.Diff o
	End Function

	Public Function Eq(ByVal o)
		If Not isArray(o) And Not isList(o) Then AB.Error.Raise 44 : Exit Function
		Dim a, e, m, i, j
		If isArray(o) Then
			a = o
			e = Ubound(a)
		ElseIf isList(o) Then
			a = o.Data
			e = o.End
		End If
		m = AB.C.IIF([End] < e, [End], e)
		For i = 0 To m
			If Compare__("gt", At(i), a(i)) Then
				Eq = 1 : Exit Function
			ElseIf Compare__("lt", At(i), a(i)) Then
				Eq = -1 : Exit Function
			End If
		Next
		If [End] > e Then
			Eq = 1
		ElseIf [End] < e Then
			Eq = -1
		Else
			Eq = 0
		End If
	End Function

	Public Function Son(ByVal o)
		If Not isArray(o) And Not isList(o) Then AB.Error.Raise 44 : Exit Function
		Son = True
		Dim i
		If isList(o) Then o = o.Data
		For i = 0 To Ubound(o)
			If Not Has(o(i)) Then Son = False : Exit Function
		Next
	End Function

	'===以下辅助函数===

		Private Sub CloneDic__(ByRef map, ByRef hash)
			Dim key
			If map.Count > 0 Then map.RemoveAll
			For Each key In hash
				map(key) = hash(key)
			Next
		End Sub

		Private Sub Map__(ByVal f, ByVal t)
			Dim i, tmp
			For i = 0 To [End]
				tmp = Value__(At(i))
				If t = 0 Then
					At(i) = Eval(f & "("& tmp &")")
				ElseIf t = 1 Then
					ExecuteGlobal f & "("& tmp &")"
				End If
			Next
		End Sub

		Private Function Value__(ByVal s)
			Dim tmp
			Select Case VarType(s)
				Case 7,8 tmp = """" & s & """"
				Case Else tmp = s
			End Select
			Value__ = tmp
		End Function

		Private Sub RemoveMap__(ByVal i)
			If o_map.Exists(i) Then
				o_map.Remove o_map(i)
				o_map.Remove i
			End If
		End Sub

		Private Function indexOf__(ByVal arr, ByVal v)
			Dim i
			indexOf__ = -1
			For i = 0 To UBound(arr)
				If Compare__("eq", arr(i),v) Then
					indexOf__ = i
					Exit For
				End If
			Next
		End Function

		Private Sub Data__(ByVal a, ByVal t)
			Dim arr, i, j
			If isArray(a) Then
				a_list = a
				Size = Ubound(a_list) + 1
				If t = 0 Then Exit Sub
				For i = 0 To Ubound(a)
					If Instr(a(i),":")>0 Then
						j = AB.C.CLeft(a(i),":")
						If Not o_map.Exists(j) Then
							o_map.Add i, j
							o_map.Add j, i
						End If
						a(i) = AB.C.CRight(a(i),":")
					End If
				Next
				a_list = a
			Else
				arr = Split(a, " ")
				a_list = arr
				Size = Ubound(a_list) + 1
				If t = 0 Then Exit Sub
				If Instr(a, ":")>0 Then
					For i = 0 To Ubound(arr)
						If Instr(arr(i),":")>0 Then
							j = AB.C.CLeft(arr(i),":")
							If Not o_map.Exists(j) Then
								o_map.Add i, j
								o_map.Add j, i
							End If
							arr(i) = AB.C.CRight(arr(i),":")
						End If
					Next
				End If
				a_list = arr
			End If
		End Sub

		Private Function Compare__(ByVal t, ByVal a, ByVal b)
			Dim isStr : isStr = False
			If VarType(a) = 8 Or VarType(b) = 8 Then
				isStr = True
				If IsNumeric(a) And IsNumeric(b) Then isStr = False
				If IsDate(a) And IsDate(b) Then isStr = False
			End If
			If isStr Then
				Select Case LCase(t)
					Case "lt" Compare__ = (StrComp(a,b,i_comp) = -1)
					Case "gt" Compare__ = (StrComp(a,b,i_comp) = 1)
					Case "eq" Compare__ = (StrComp(a,b,i_comp) = 0)
					Case "lte" Compare__ = (StrComp(a,b,i_comp) = -1 Or StrComp(a,b,i_comp) = 0)
					Case "gte" Compare__ = (StrComp(a,b,i_comp) = 1 Or StrComp(a,b,i_comp) = 0)
				End Select
			Else
				Select Case LCase(t)
					Case "lt" Compare__ = (a < b)
					Case "gt" Compare__ = (a > b)
					Case "eq" Compare__ = (a = b)
					Case "lte" Compare__ = (a <= b)
					Case "gte" Compare__ = (a >= b)
				End Select
			End If
		End Function

		Private Sub Search__(ByVal s, ByVal keep)
			Dim arr,i,tmp
			arr = Filter(a_list, s, keep, i_comp)
			If o_map.Count = 0 Then
				Data = arr
			Else
				AddHash__ arr
			End If
		End Sub

		Private Function SortArray(ByRef arr, ByRef low, ByRef high)
			If Not IsArray(arr) Then Exit Function
			If AB.C.IsNul(arr) Then Exit Function
			Dim l, h, m, v, x
			l = low : h = high
			m = (low + high) \ 2 : v = arr(m)
			Do While (l <= h)
				Do While (Compare__("lt",arr(l),v) And l < high)
					l = l + 1
				Loop
				Do While (Compare__("lt",v,arr(h)) And h > low)
					h = h - 1
				Loop
				If l <= h Then
					x = arr(l) : arr(l) = arr(h) : arr(h) = x
					l = l + 1 : h = h - 1
				End If
			Loop
			If (low < h) Then arr = SortArray(arr, low, h)
			If (l < high) Then arr = SortArray(arr,l, high)
			SortArray = arr
		End Function

		Private Sub AddHash__(ByVal arr)
			Dim tmp
			If o_hash.Count > 0 Then o_hash.RemoveAll
			For i = 0 To Ubound(arr)
				If IndexOfHash(arr(i))>"" Then
					tmp = IndexOfHash(arr(i))
					If Not o_hash.Exists(tmp) Then
						o_hash.Add i, tmp
						o_hash.Add tmp, i
					End If
				End If
			Next
			Data = arr
			CloneDic__ o_map, o_hash
			o_hash.RemoveAll
		End Sub

		Private Sub UpFrom__(ByVal n, ByVal i)
			If n = i Then Exit Sub
			If o_map.Exists(i) Then
				o_map(o_map(i)) = n
				o_map(n) = o_map(i)
				o_map.Remove i
			End If
			At(n) = At(i)
		End Sub

		Private Sub Select__(ByVal f, ByVal t)
			Dim i, j, k, tmp, arr
			arr = Array() : j = 0
			If o_hash.Count>0 Then o_hash.RemoveAll
			k = "i"
			If AB.C.Test(f,"[a-zA-Z]+:(.+)") Then
				k = AB.C.CLeft(f,":")
				f = AB.C.CRight(f,":")
			End If
			k = "%" & k
			For i = 0 To [End]
				tmp = Replace(Trim(f), k, Value__(At(i)))
				If t = 0 Then
					tmp = Eval(tmp)
				ElseIf t = 1 Then
					tmp = (Not Eval(tmp))
				End If
				If tmp Then
					ReDim Preserve arr(j)
					arr(j) = At(i)
					If o_map.Exists(i) Then
						o_hash.Add j, o_map(i)
						o_hash.Add o_map(i), j
					End If
					j = j + 1
				End If
			Next
			Data = arr
			CloneDic__ o_map, o_hash
			o_hash.RemoveAll
		End Sub

		Private Function IsList(ByVal o)
			IsList = (Lcase(TypeName(o)) = "cls_ab_list")
		End Function

End Class
%>